Skip to content

fix(react-headless-components-preview): provide MenuSplitGroup's context - #36669

Open
Ray Knight (ArrayKnight) wants to merge 3 commits into
microsoft:masterfrom
ArrayKnight:fix/headless-menu-split-group-context-36651
Open

fix(react-headless-components-preview): provide MenuSplitGroup's context#36669
Ray Knight (ArrayKnight) wants to merge 3 commits into
microsoft:masterfrom
ArrayKnight:fix/headless-menu-split-group-context-36651

Conversation

@ArrayKnight

@ArrayKnight Ray Knight (ArrayKnight) commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

The headless MenuSplitGroup calls renderMenuSplitGroup(state) with no contexts argument. useIsInMenuSplitGroup compares the context value it receives against the module-level default by identity, so with nothing provided the comparison is always false and no descendant can tell it is inside a split group. The user-visible consequence is that the gutter suppression a split group is supposed to apply — the icon and checkmark columns the trigger half drops in the Griffel-styled equivalent — never fires, because it is gated on exactly this hook.

The fix provides the contexts argument, memoized on state.setMultiline so the identity is stable across renders (an inline object literal would defeat the comparison in the other direction, re-firing every render). setMultiline itself stays the documented no-op — this changes what descendants can observe, not what the group does.

Fixes #36651.

Extracted from #36656 per maintainer request — each in-tree fix from that PR as an isolated change.

renderMenuSplitGroup falls back to menuSplitGroupContextDefaultValue when no
contexts argument is supplied, and MenuSplitGroup supplies none.
useIsInMenuSplitGroup compares against that default by identity, so it
returns false for every descendant of a headless MenuSplitGroup.

The visible effect is in useMenuItemBase's useIconAndCheckmarkAlignment: a
submenu trigger inside a split group is supposed to drop its icon and
checkmark gutters, and instead keeps them, widening one half of the group
by the gutter plus the row gap whenever the surrounding MenuList sets
hasIcons or hasCheckmarks.

Pass the state's own context value so the identity differs from the
default. The setMultiline it carries stays a no-op: the multiline
attribute remains a styling concern for consumers, as documented on the
hook.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013wmpBCYJpDJCLXcScCWz1i
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Aj9uA3rCVgosnh2zNn8qkc
// useIsInMenuSplitGroup compares the provided value against the module-level default BY IDENTITY,
// so supplying a contexts argument is what lets a descendant tell it is inside a split group. The
// memo keeps that identity stable across renders; setMultiline stays the documented no-op.
const contexts = React.useMemo(

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we should probably create a useMenuSplitGroupContextValues hook and export it from the package

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 5e8a57c — extracted useMenuSplitGroupContextValues (with a MenuSplitGroupContextValues type, which @fluentui/react-menu doesn't export), exported it from the MenuSplitGroup barrel and the ./menu subpath, regenerated etc/menu.api.md, and added a regression test that fails without the contexts argument (split-group trigger keeps its icon gutter).

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

📊 Bundle size report

Package & Exports Baseline (minified/GZIP) PR Change
react-headless-components-preview
react-headless-components-preview: entire library
240.515 kB
67.828 kB
239.293 kB
67.376 kB
-1.222 kB
-452 B
Unchanged fixtures
Package & Exports Size (minified/GZIP)
react-headless-components-preview
@fluentui/react-headless-components-preview/tag-picker
54.012 kB
17.756 kB
react-headless-components-preview
@fluentui/react-headless-components-preview/teaching-popover
36.073 kB
12.006 kB
🤖 This report was generated against d65114cf781859465a7862689dbb8b48a5288e78

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟢 Approval recommended

The focused fix mirrors the established implementation and includes regression coverage and release metadata.

Pull request overview

Fixes headless MenuSplitGroup descendant detection by supplying a stable context value.

Changes:

  • Adds and exports useMenuSplitGroupContextValues.
  • Passes context into renderMenuSplitGroup.
  • Adds regression coverage, API metadata, and a patch change file.

Merge confidence: 100/100

File summaries
File Description
library/src/menu.ts Exports the new context API.
useMenuSplitGroupContextValues.ts Creates the stable context value.
MenuSplitGroup.tsx Supplies context during rendering.
MenuSplitGroup/index.ts Adds local exports.
Menu.test.tsx Tests split-trigger gutter suppression.
components/Menu/index.ts Propagates component exports.
library/etc/menu.api.md Updates the generated API report.
change/...json Records the patch release.
Review details
  • Files reviewed: 8/8 changed files
  • Comments generated: 0
  • Review effort level: Balanced

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

@github-actions

github-actions Bot commented Sep 3, 2026

Copy link
Copy Markdown

Pull request demo site: URL

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: headless MenuSplitGroup renders without a contexts argument, so useIsInMenuSplitGroup can never return true

3 participants